using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
namespace Test {
	class Grad {
		internal static Color HeatMap(float dummy,float max) {
			if(dummy<0)
				return Color.DeepSkyBlue;
			int pct=(int)(dummy*100/max);
			string key="-"+pct;
			Color col;
			int red=Math.Min(510*pct/100,255);
			int gre=Math.Min(510-510*pct/100,255);
			int blu=0;
			if(pct<20)
			{
				blu=240-220*pct*5/100;
				red=240-220*pct*5/100;
			}
			col=Color.FromArgb(red,gre,blu);
			return col;
		}
		static void MainX() {
			Color c=new Gradient(Color.White,Color.Gray,Color.Black).Get(1);
			string filename="img00.png";
			using(Bitmap bmp=new Bitmap(300,300))
			using(Graphics g=Graphics.FromImage(bmp))
			{
				g.Clear(Color.White);
				List<Gradient> lg=new List<Gradient>();
				lg.Add(new Gradient(Color.White,Color.Lime,Color.Yellow,Color.Orange,Color.Red));
				lg.Add(new Gradient(Color.White,Color.Lime,Color.Yellow,Color.Orange,Color.Red,Color.DarkRed));
				lg.Add(new Gradient(Color.White,Color.LawnGreen,Color.Yellow,Color.Red));
				lg.Add(new Gradient(Color.White,Color.Lime,Color.Yellow,Color.Red));
				lg.Add(new Gradient(Color.White,Color.LawnGreen,Color.Green,Color.Yellow,Color.Red,Color.Maroon));
				lg.Add(new Gradient(Color.White,Color.PaleGreen,Color.Yellow,Color.Red,Color.Brown));
				lg.Add(new Gradient(Color.White,Color.Green,Color.Yellow,Color.Red,Color.Maroon));
				lg.Add(new Gradient(Color.White,Color.Aqua,Color.Green,Color.Yellow,Color.Red,Color.DarkRed));
				lg.Add(new Gradient(Color.DarkViolet,Color.DarkMagenta,Color.Purple,Color.Blue,Color.Aqua,Color.White,Color.YellowGreen,Color.Green,Color.Yellow,Color.Orange,Color.Red,Color.Brown));
				lg.Add(new Gradient(Color.SlateBlue,Color.Blue,Color.LightSkyBlue,Color.White,Color.Green,Color.Yellow,Color.Red));
				lg.Add(new Gradient(Color.Red,Color.Yellow,Color.White,Color.GreenYellow,Color.Green));
				lg.Add(new Gradient(Color.Red,Color.Orange,Color.Yellow,Color.White,Color.GreenYellow,Color.LightGreen,Color.Green));
				lg.Add(new Gradient(Color.Blue,Color.White,Color.Green));
				lg.Add(new Gradient(Color.Red,Color.White,Color.YellowGreen));
				lg.Add(new Gradient(Color.Brown,Color.Red,Color.Orange,Color.Yellow,Color.GreenYellow,Color.YellowGreen,Color.Green));
				lg.Add(new Gradient(Color.Red,Color.White,Color.Blue));
				lg.Add(new Gradient(Color.Red,Color.Indigo,Color.Blue));
				lg.Add(new Gradient(Color.Red,Color.BlueViolet,Color.Blue));
				lg.Add(new Gradient(Color.Red,Color.Blue));
				lg.Add(new Gradient(Color.Orange,Color.Blue,Color.Red));
				lg.Add(new Gradient(Color.Red,Color.Indigo,Color.Blue,Color.Brown,Color.Orange,Color.Yellow,Color.Green,Color.Gray));
				lg.Add(new Gradient(Color.White,Color.Black));
				lg.Add(new Gradient(Color.White,Color.Silver,Color.Black));
				lg.Add(new Gradient(Color.White,Color.Gray,Color.Black));
				lg.Add(new Gradient(Color.Black,Color.Black,Color.Black,Color.White,Color.White,Color.White,Color.White,Color.Black,Color.White,Color.White,Color.Black));
				lg.Add(new Gradient(Color.Black,Color.Yellow,Color.White));
				lg.Add(new Gradient(Color.Black,Color.Brown,Color.Red,Color.Yellow,Color.GreenYellow,Color.White));
				int top=0;
				int height=bmp.Height/(lg.Count);
				Stopwatch sw=Stopwatch.StartNew();
				foreach(Gradient gr in lg)
				{
					for(int i=0;i<=bmp.Width;i++)
						g.DrawLine(new Pen(gr.Get((float)i/bmp.Width),2),i,top,i,top+height);
					top+=height;
				}
				//for(int i=0;i<=bmp.Width;i++)
				//  g.DrawLine(new Pen(Grad.HeatMap((float)i/bmp.Width,1),2),i,top,i,top+height);
				//top+=height;
				Console.WriteLine(sw.Elapsed);
				bmp.Save(filename,ImageFormat.Png);
			}
			Process.Start(filename);
		}
	}
	class Gradient {
		Range[] RanArray;
		public Gradient(params Color[] args) {
			RanArray=new Range[args.Length-1];
			for(int i=0;i<args.Length-1;i++)
				RanArray[i]=new Range((float)i/(args.Length-1),args[i],(float)(i+1)/(args.Length-1),args[i+1]);
		}
		public Color Get(float percent) {
			if(percent<0)
				percent=0;
			if(percent>1)
				percent=1;
			foreach(Range ran in RanArray)
				if(ran.InRange(percent))
					return ran.GetColor(percent);
			throw new Exception();
		}
		class Range {
			public Range(float m1,Color c1,float m2,Color c2) {
				minLimit=m1;
				maxLimit=m2;
				minCol=c1;
				maxCol=c2;
			}
			public bool InRange(float f) {
				return minLimit<=f&&f<=maxLimit;
			}
			float minLimit;
			float maxLimit;
			Color minCol;
			Color maxCol;
			public Color GetColor(float percent) {
				float fraction=(percent-minLimit)/(maxLimit-minLimit);
				return Interpolate(maxCol,minCol,fraction);
			}
			Color Interpolate(Color color1,Color color2,float fraction) {
				float r=Interpolate(color1.R,color2.R,fraction);
				float g=Interpolate(color1.G,color2.G,fraction);
				float b=Interpolate(color1.B,color2.B,fraction);
				return Color.FromArgb((int)r,(int)g,(int)b);
			}
			float Interpolate(float d1,float d2,float fraction) {
				return d2+(d1-d2)*fraction;
			}
		}
	}
}
